//
// Created by Administrator on 2022/6/12.
//

//
// Created by gogoqiu on 2022/6/11.
//

#include <cstdio>
#include <sys/types.h>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <fcntl.h>
#include <boost/filesystem.hpp>
#include <iostream>
#include <boost/property_tree/ini_parser.hpp>
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "string"
#include "../../public/windows/utils.h"

#define BUFF_LEN 65536

using namespace std;
using namespace rapidjson;

static int post_info ( int fd, struct sockaddr* dst, Document &document ){

    StringBuffer stringBuffer;
    Writer<StringBuffer> writer( stringBuffer );
    document.Accept(writer );

    socklen_t len;
    struct sockaddr_in src;

    char buf[BUFF_LEN];
    char current[256];
    int err;
    GetNowTime( current );
    printf( "%s\n", current );

    len = sizeof(*dst);
    //printf("client:%s\n",buf);  //打印自己发送的信息
    //const char* s = buffer.GetString();
    sendto( fd, stringBuffer.GetString(), stringBuffer.GetSize(), 0, dst, len );
    memset( buf, 0, BUFF_LEN );
    //接收1024
    //实际长度大于1024的问题
    err = recvfrom( fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src, &len );  //接收来自server的信息
    if( err> 0 )
        printf("server: \nlen: %d\nresponse: %s\n", err, buf );
    else
        printf( "error: %d\n", err );
}

static void test_json_post(){

}

/*
 * current: 2022年06月12日17:19:29
ip:112.0.164.41
{"host_name":"notepad"}
Error(offset 0): No error.
Udp udp_response:input json error!
Err: 17, Response size: 17
 */
int main(int argc, char* argv[])
{

    //

    socklen_t len;
    struct sockaddr_in src;

    char buf[BUFF_LEN];
    char current[256];
    //sockaddr* dst;

    if( argc!=4 ){
        fprintf( stderr, "USAGE: %s config_file_path to_host message", argv[0] );
        exit(-1);
    }
    const char * message = argv[3];
    const char * to_host = argv[2];
    const char * config_file_path = argv[1];

    if (!boost::filesystem::exists(config_file_path )) {
        std::cerr << "config file not exists." << std::endl;
        exit(-1);
    }

    boost::property_tree::ptree root_node, tag_system;
    boost::property_tree::ini_parser::read_ini(config_file_path,
                                               root_node );
    tag_system = root_node.get_child("main");
    if(tag_system.count("server-ip") != 1) {
        std::cerr << "server-ip node not exists." << std::endl;
        exit(-1);
    }
    string server_ip = tag_system.get<string>("server-ip");
    std::cout << "server-ip: " << server_ip << std::endl;

    if(tag_system.count("server-port") != 1) {
        std::cerr << "server-port node not exists." << std::endl;
        exit(-1);
    }
    //ignore check the port format: port format
    int server_port = tag_system.get<int>("server-port");
    std::cout << "server-port: " << server_port << std::endl;

    char computer[256];
    gethostname( computer,256);

    char datetime[256];
    GetNowTime( datetime );

    Document document;
    document.SetObject();
    auto &allocator = document.GetAllocator();
    Value messages( kArrayType );
    Value value( kObjectType );
    value.AddMember( "to_host", StringRef( to_host ), allocator );
    value.AddMember( "from_host", StringRef( computer ), allocator );
    value.AddMember( "message", StringRef( message ), allocator );
    value.AddMember( "datetime", StringRef( datetime ), allocator );

    messages.PushBack( value, allocator );
    document.AddMember( "messages", messages, allocator );
    document.AddMember( "host_name", StringRef( computer ), allocator );

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer );
    document.Accept(writer );
    //post the messages to the server
    int client_fd;
    struct sockaddr_in ser_addr;

    client_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(client_fd < 0){
        printf("create socket fail!\n");
        return -1;
    }

    //setNonblocking(client_fd);
    memset( &ser_addr, 0, sizeof(ser_addr) );
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = inet_addr( server_ip.c_str() );
    //ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //注意网络序转换
    ser_addr.sin_port = htons( server_port );  //注意网络序转换

    //post_info( client_fd, (sockaddr*)&ser_addr, document );
    test_json_post();

    //return 0;
    int err;
    len = sizeof(ser_addr);
    /*
    if( !doc.Parse( buffer.GetString() ).HasParseError()){
        printf( "json ok\n");
    }else{
        exit(-1);
    }
*/
    err = sendto( client_fd, buffer.GetString(), buffer.GetSize(),
                  0, (struct sockaddr*)&ser_addr, len );

    if( err> 0 )
        printf("%d\n", err );
    memset( buf, 0, BUFF_LEN );
    printf( "sent and starting recv...\n" );
    err = recvfrom( client_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src, &len );  //接收来自server的信息
    if( err> 0 )
        printf("server:%s\n", buf );
    printf( "buf: %s\n%d\n", buf, len );
    close( client_fd );
    return 0;
}